package controller.billing.document;

import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;

import model.Belegung;
import model.Kunde;
import model.Rechnung;

public class BillDocumentCreator {

	private static final String BILL_TEMPLATE_PATH = "BillTemplates/bill_template.txt";
	private static final String BILL_TEMPLATE_PATH_EARLY = "BillTemplates/bill_template_early_departure.txt";
	private static final String BILL_TEMPLATE_PATH_CANCEL = "BillTemplates/bill_template_cancel_reservation.txt";
	
	
	public File createBillDocument(Rechnung bill) throws IOException{
		
		// determine bill type : normal, early departure, cancellation
		Date billDate = bill.getDatum();
		
		File billFile;
		
		if(billDate.before(bill.getReservierung().getVon()) || billDate.equals(bill.getReservierung().getVon())){
			// billDate < reservation arrival date => cancellation
			billFile = copyFromTemplate(BILL_TEMPLATE_PATH_CANCEL, "BillDocuments/Bill"+bill.getPayingCustomer().getNachname()+bill.getId()+".txt");
			fillKeywordsForCancellation(billFile, bill);
		}
		else if(billDate.before(bill.getReservierung().getBis())){
			// billDate < departure Date => early Departure
			billFile = copyFromTemplate(BILL_TEMPLATE_PATH_EARLY, "BillDocuments/Bill"+bill.getPayingCustomer().getNachname()+bill.getId()+".txt");
			fillKeywordsForEearlyDeparture(billFile, bill);
		}
		else{
			// equal dates or later than departure Date, pay normally
			billFile = copyFromTemplate(BILL_TEMPLATE_PATH, "BillDocuments/Bill"+bill.getPayingCustomer().getNachname()+bill.getId()+".txt");
			fillKeywords(billFile, bill);
	    }
		
		openFileInEditor(billFile);
		return billFile;
	}
	
	private void fillKeywordsForEearlyDeparture(File billFile, Rechnung bill) throws IOException {
		String text = readFileContent(billFile);
		
		Kunde cust = bill.getPayingCustomer();
		DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD);
		text = text.replace(BillTags.CUSTOMER_NAME, cust.getVorname()+" "+cust.getNachname());
		text = text.replace(BillTags.CUSTOMER_ADDRESS, cust.getRechnungsadresse() == null ? "unknown" : cust.getRechnungsadresse());
		text = text.replace(BillTags.BILLING_DATE, formatter.format(bill.getDatum()));
		text = text.replace(BillTags.ARRIVAL_DATE, formatter.format(bill.getReservierung().getVon()));
		text = text.replace(BillTags.DEPARTURE_DATE, formatter.format(bill.getReservierung().getBis()));
		text = text.replace(BillTags.BOOKING_INFOS, bill.getReason());
		
		double fine = 0;
		
		for(Belegung b : bill.getReservierung().getBelegungen()){
			fine += b.getZimmer().getPreisEZ();
		}
		
		text = text.replace(BillTags.DISCOUNT, ""+bill.getPayingCustomer().getRabat());
		
		// a fine is calculated from the average single room price, the half of this price is used as a fine
		fine /= (bill.getReservierung().getBelegungen().size() * 2);
		
		text = text.replace(BillTags.FINE_EARLY_DEPARTURE, ""+fine);
		text = text.replace(BillTags.SUM, ""+ (bill.getPreis()+fine) );
		
		writeFileContent(billFile, text);
		
	}

	private void fillKeywords(File billFile, Rechnung bill) throws IOException {
		String text = readFileContent(billFile);
		
		Kunde cust = bill.getPayingCustomer();
		DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD);
		text = text.replace(BillTags.CUSTOMER_NAME, cust.getVorname()+" "+cust.getNachname());
		text = text.replace(BillTags.CUSTOMER_ADDRESS, cust.getRechnungsadresse() == null ? "unknown" : cust.getRechnungsadresse());
		text = text.replace(BillTags.BILLING_DATE, formatter.format(bill.getDatum()));
		text = text.replace(BillTags.ARRIVAL_DATE, formatter.format(bill.getReservierung().getVon()));
		text = text.replace(BillTags.DEPARTURE_DATE, formatter.format(bill.getReservierung().getBis()));
		text = text.replace(BillTags.BOOKING_INFOS, bill.getReason());
		text = text.replace(BillTags.DISCOUNT, ""+bill.getPayingCustomer().getRabat());
		text = text.replace(BillTags.SUM, ""+bill.getPreis());
		
		writeFileContent(billFile, text);
	}

	private void fillKeywordsForCancellation(File billFile, Rechnung bill) throws IOException {
		String text = readFileContent(billFile);
		
		Kunde cust = bill.getPayingCustomer();
		DateFormat formatter = DateFormat.getDateInstance(DateFormat.DATE_FIELD);
		text = text.replace(BillTags.CUSTOMER_NAME, cust.getVorname()+" "+cust.getNachname());
		text = text.replace(BillTags.CUSTOMER_ADDRESS, cust.getRechnungsadresse() == null ? "unknown" : cust.getRechnungsadresse());
		text = text.replace(BillTags.BILLING_DATE, formatter.format(bill.getDatum()));
		text = text.replace(BillTags.ARRIVAL_DATE, formatter.format(bill.getReservierung().getVon()));
		text = text.replace(BillTags.DEPARTURE_DATE, formatter.format(bill.getReservierung().getBis()));
		text = text.replace(BillTags.BOOKING_INFOS, bill.getReason());
		double fine = 0;

		// a fine is 10% from the actual price
		fine = Math.round(Math.abs(bill.getPreis() / 10));
		
		text = text.replace(BillTags.FINE_CANCELLATION, ""+fine);
		text = text.replace(BillTags.SUM, ""+ fine );
		
		writeFileContent(billFile, text);
		
	}

	private boolean openFileInEditor(final File file) {
		  if (!Desktop.isDesktopSupported()) {
		    return false;
		  }

		  Desktop desktop = Desktop.getDesktop();

		  try {
		    desktop.open(file);
		  } catch (IOException e) {
		    
			e.printStackTrace();
		    return false;
		  }

		  return true;
	}
	
	private File copyFromTemplate(String templatePath, String newFilePath) throws IOException{
		 File inputFile = new File(templatePath);
		    File outputFile = new File(newFilePath);

		    FileReader in = new FileReader(inputFile);
		    FileWriter out = new FileWriter(outputFile);
		    int c;

		    while ((c = in.read()) != -1)
		      {
		    	out.write(c);
		      }

		    in.close();
		    out.close();
		    
		    return outputFile;
	}
	
	private String readFileContent(File file) throws IOException{
		
		String retVal = "";
		
		FileReader fr = new FileReader(file); 
		BufferedReader br = new BufferedReader(fr); 
		String s; 
		while((s = br.readLine()) != null) { 
			retVal += s+"\n";
		} 
		fr.close(); 
		 
		return retVal;
	}
	
	private void writeFileContent(File file, String text) throws IOException{
		FileWriter fw = new FileWriter(file);
		fw.write(text);
		fw.close();
	}
}
